package com.hycat.mail.ware.service.impl;

import com.hycat.mail.common.exception.MailException;
import com.hycat.mail.common.model.ExceptionEnum;
import com.hycat.mail.ware.client.OrderClient;
import com.hycat.mail.ware.entity.WareOrderTaskDetailEntity;
import com.hycat.mail.ware.entity.WareOrderTaskEntity;
import com.hycat.mail.ware.mq.entity.UnLockStockTo;
import com.hycat.mail.ware.service.WareOrderTaskDetailService;
import com.hycat.mail.ware.service.WareOrderTaskService;
import com.hycat.mail.ware.vo.OrderEntityVo;
import com.hycat.mail.ware.vo.OrderItemEntityVo;
import com.hycat.mail.ware.vo.OrderLockStockVo;
import com.rabbitmq.client.Channel;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hycat.mail.common.utils.PageUtil;
import com.hycat.mail.common.utils.Query;

import com.hycat.mail.ware.dao.WareSkuDao;
import com.hycat.mail.ware.entity.WareSkuEntity;
import com.hycat.mail.ware.service.WareSkuService;
import org.springframework.transaction.annotation.Transactional;


@Service
public class WareSkuServiceImpl extends ServiceImpl<WareSkuDao, WareSkuEntity> implements WareSkuService {

    @Autowired
    private OrderClient orderClient;

    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Autowired
    private WareOrderTaskService wareOrderTaskService;

    @Autowired
    private WareOrderTaskDetailService wareOrderTaskDetailService;

    @Override
    public PageUtil queryPage(Map<String, Object> params) {
        IPage<WareSkuEntity> page = this.page(
                new Query<WareSkuEntity>().getPage(params),
                new QueryWrapper<WareSkuEntity>()
        );

        return new PageUtil(page);
    }

    @Override
    public Map<Long, Long> stockDetails(List<Long> skuIds) {
        Map<Long, Long> map = new HashMap<>();
        skuIds.stream()
                .map((skuId) -> {
                    Long stock = baseMapper.stockDetails(skuId);
                    map.put(skuId, stock);
                    return null;
                });
        return map;
    }

    @Override
    @Transactional
    public Boolean orderLockStock(OrderLockStockVo orderLockStockVo) {
        String orderSn = orderLockStockVo.getOrderSn();
        List<OrderItemEntityVo> items = orderLockStockVo.getItems();

        //1.构建库存快照表
        WareOrderTaskEntity taskEntity = new WareOrderTaskEntity();
        taskEntity.setOrderSn(orderSn);
        wareOrderTaskService.save(taskEntity);

        //2.循环扣减库存
        for(int i = 0; i < items.size(); i++) {
            //(1).查询有库存的仓库Id select * from ware_sku where sku_id = #{sku_id}
            List<WareSkuEntity> hasStock = baseMapper.getHasStock(items.get(i).getSkuId());

            //(2).循环扣减库存 update set stock_locked = stock_locked + #{count} where id = #{id}
            Integer totalCount = items.get(i).getSkuQuantity();
            for(int j = 0; j < hasStock.size(); j++) {
                //锁定库存扣减完毕
                if(totalCount == 0) {
                    break;
                }
                //获得本仓库真实库存
                WareSkuEntity wareSku = hasStock.get(j);
                Integer realStock = wareSku.getStock() - wareSku.getStockLocked();
                //统一变量:本次库存快照详情表锁定的库存数量
                Integer currentStock = 0;
                if(totalCount <= realStock) {
                    baseMapper.lockStock(wareSku.getId(), totalCount);
                    currentStock = totalCount;
                    totalCount = 0;
                } else {
                    baseMapper.lockStock(wareSku.getId(), realStock);
                    currentStock = realStock;
                    totalCount -= realStock;
                }
                //3.构建库存详情快照表
                WareOrderTaskDetailEntity taskDetailEntity = WareOrderTaskDetailEntity.from(wareSku, currentStock);
                taskDetailEntity.setTaskId(taskEntity.getId());
                taskDetailEntity.setWareSkuId(wareSku.getId());
                wareOrderTaskDetailService.save(taskDetailEntity);

                //4.发送MQ:已经成功锁定库存
                UnLockStockTo unLockStockTo = new UnLockStockTo(taskDetailEntity.getId(), orderSn);
                rabbitTemplate.convertAndSend("stock_event_exchange", "stock.locked", unLockStockTo);
            }
            //所有仓库的库存都不足以扣减
            if(totalCount > 0) {
                throw new MailException(ExceptionEnum.WARE_SKU_STOCK_ERROR);
            }
        }
        return true;
    }

    /**
     * 快照作用：当锁库存发生回滚,没有快照表无法判断库存是否被释放
     * 释放库存
     *      1.订单详情快照表未查到 : byId为空
     *      2.订单详情快照表未查到 : byId不为空
     *           (1).订单出现问题导致库存未回滚 : orderSn找不到(释放库存)
     *           (2).用户取消订单/订单自动取消(超过30min未付款) : orderSn找到、订单状态为已取消(释放库存)
     */
    @Override
    public void unLockStock(UnLockStockTo unLockStockTo) {
        Long taskDetailsId = unLockStockTo.getTaskDetailsId();
        String orderSn = unLockStockTo.getOrderSn();

        WareOrderTaskDetailEntity byId = wareOrderTaskDetailService.getById(taskDetailsId);
        if(!Objects.isNull(byId)) {
            OrderEntityVo byOrderSn = orderClient.getByOrderSn(orderSn);
            if(!Objects.isNull(byOrderSn) || byOrderSn.getPayType() == 4) {
                //1.解锁库存
                baseMapper.unLockStock(byId.getWareSkuId(), byId.getSkuNum());
                //2.库存快照详情luck_status置为1
                byId.setLockStatus(1);
                wareOrderTaskDetailService.save(byId);
            }
        }
    }
}